package worker

import (

	"encoding/json"
	"errors"

	"sync"
	"time"

	"github.com/astaxie/beego"
	"github.com/astaxie/beego/httplib"
	"publish/pub-lib"
	"publish/model"
)

type CallResp struct {
	Code    int         `json:"code"`
	Message string      `json:"message"`
}

type CallTaskResp struct {
	Code    int         `json:"code"`
	Message string      `json:"message"`
	Data    pub_lib.Task `json:"data"`
}


func StartWorker(remote string) *Worker {
	worker := &Worker{
		remote: remote,
		exit:   make(chan struct{}),
	}
	go worker.run()
	return worker
}

type Worker struct {
	remote string
	exit   chan struct{}
	wait   sync.WaitGroup
}

func (w *Worker) Stop() {
	close(w.exit)
	w.wait.Wait()
}

func (w *Worker) run() {
	w.wait.Add(1)
	defer w.wait.Done()

	for {
		select {
		case <-w.exit:
			beego.Warning("结束进程")
			return
		default:
		}

		task, err := w.getTask()
		if err != nil {
			beego.Warning(err)
			time.Sleep(time.Second * 10)
			continue
		}

		cb := model.PubResult{TaskId: task.Id, Result: "开始发布", Type: model.Pub_Status_Pub_Start}
		_, err = w.callback(cb)
		if err != nil {
			beego.Error("回调失败： 状态开始发布", err)
			continue
		}

		err = pub_lib.Publish(task)
		if err != nil {
			beego.Error("发布失败：TaskId:", task.Id, " err:", err.Error())
			cb := model.PubResult{TaskId: task.Id, Result: err.Error(), Type: model.Pub_Status_Fail, Success: false}
			w.callback(cb)
			continue
		}

		cb = model.PubResult{TaskId: task.Id, Result: "发布成功", Type: model.Pub_Status_Success, Success: true}
		w.callback(cb)
	}
}

func (w *Worker) getTask() (pub_lib.Task, error) {

	task := CallTaskResp{}
	err := httplib.Get(w.remote + `/api/task/get`).ToJSON(&task)
	if err != nil {
		return task.Data, errors.New("没有获取到新的任务")
	}
	if task.Data.Id <= 0 {
		return task.Data, errors.New("没有获取到新的任务")
	}
	return task.Data, nil
}

func (w *Worker) callback(cb model.PubResult) (*CallResp, error) {
	req, err := httplib.Post(w.remote + `/api/task/callback`).JSONBody(cb)
	if err != nil {
		beego.Error(err)
		return nil, err
	}
	result, err := req.Bytes()
	if err != nil {
		beego.Error(err)
		return nil, err
	}
	resp := &CallResp{}
	if err := json.Unmarshal(result, resp); err != nil {
		return nil, err
	}

	return resp, nil
}
